package org.guitycrown.Command.NetworkCommand;

import java.io.IOException;
import java.util.Vector;

import org.snmp4j.CommunityTarget;
import org.snmp4j.PDU;
import org.snmp4j.Snmp;
import org.snmp4j.TransportMapping;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.Integer32;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.UdpAddress;
import org.snmp4j.smi.VariableBinding;
import org.snmp4j.transport.DefaultUdpTransportMapping;

/**
 * Created by kira on 2016/5/29.
 */
public class SnmpGetter {
    String ipFromInput, commFromInput, oidFromInput, verFromInput;

    public SnmpGetter(String ip, String comm, String oid, String ver) {
        this.ipFromInput = ip;
        this.commFromInput = comm;
        this.oidFromInput = oid;
        this.verFromInput = ver;
    }

    /*
     *
     */
    public void SentGetSnmp() throws IOException {

        TransportMapping transport = new DefaultUdpTransportMapping();
        transport.listen();

        //Target
        CommunityTarget target = CreateAndSetTarget();

        //PDU
        PDU pdu = CreateAndSetPdu();

        //SNMP
        Snmp snmp = new Snmp(transport);

        //System.out.println("Sending request to " + ipFromInput + " ...");
        ResponseEvent response = snmp.get(pdu, target);

        if (response != null) {
            //System.out.println("Got response from " + ipFromInput);
            PDU responsePdu = response.getResponse();

            if (responsePdu != null) {
                int errorStatus = responsePdu.getErrorStatus();
                int errorIndex = responsePdu.getErrorIndex();
                String errorStatusText = responsePdu.getErrorStatusText();

                if (errorStatus == PDU.noError) {
                    readResponse(responsePdu.getVariableBindings());
                    //System.out.println(responsePdu.getVariableBindings().getClass());
                    //System.out.println("SNMP get response: " + responsePdu.getVariableBindings());
                } else {
                    System.out.println("Error: Request Failed");
                    System.out.println("Error Status: " + errorStatus);
                    System.out.println("Error Index: " + errorIndex);
                    System.out.println("Error Status Text: " + errorStatusText);
                }
            } else {
                System.out.println("Error: PDU response is null");
            }
        } else {
            System.out.println("Error: Agent Timeout");
        }
        snmp.close();
    }

    /*
     *
     */
    private CommunityTarget CreateAndSetTarget() {
        CommunityTarget target = new CommunityTarget();
        target.setCommunity(new OctetString(commFromInput));
        target.setVersion(getSnmpVerFromBaseOnInput());
        target.setAddress(new UdpAddress(ipFromInput + "/161"));
        target.setRetries(2);
        target.setTimeout(1000);
        return target;
    }

    private void readResponse(Vector<? extends VariableBinding> responseVector) {
        if (responseVector.size() == 1) {
            String splits[] = responseVector.get(0).toString().split("=");

            String response = splits[1];
            System.out.println("SNMP response: " + response);

        }
        //TODO save it in DB
    }

    /*
     *
     */
    private PDU CreateAndSetPdu() {
        PDU pdu = new PDU();
        pdu.add(new VariableBinding(new OID(oidFromInput)));
        pdu.setType(PDU.GET);
        pdu.setRequestID(new Integer32(2));
        return pdu;
    }

    /*
     * Base on input data parses SNMP version.
     * Default it's 2c.
     */
    private int getSnmpVerFromBaseOnInput() {
        if (verFromInput == null) {
            return SnmpConstants.version2c;
        }

        switch (verFromInput) {
            case "1":
                return SnmpConstants.version1;
            case "2c":
                return SnmpConstants.version2c;
            case "3":
                return SnmpConstants.version3;
            default:
                return SnmpConstants.version2c;
        }
    }
}
